package com.mysen.sso.controller;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.mysen.exception.MaikeServiceException;
import com.mysen.model.Response;
import com.mysen.spring.plugin.WebContextUtil;
import com.mysen.sso.util.SFTPClient;
import com.mysen.util.SimpleChaos;
import com.mysen.util.UnmodifiableHashSet;

@RequestMapping("file")
@Controller
public class FileController {

	private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class);

	@Autowired
	private SFTPClient client;
	
	@Autowired
	private HttpServletRequest request;
	
	private static final Set<String> FILETYPES = new UnmodifiableHashSet<>("userimg", "bussimg");
	
	@PostMapping("upload/{type}")
	@ResponseBody
    public Response<?> fileUpload(@RequestParam("file") CommonsMultipartFile file, @PathVariable("type") String type) throws IOException {
		if(!FILETYPES.contains(type)) {
			throw new MaikeServiceException(Response.MSG_PARAM_ERROR);
		}
		Response<Map<String,String>> resp = new Response<>();
    	FileItem fileItem = null;
    	try {
    		fileItem = file.getFileItem();
	    	String format = new SimpleDateFormat("yyyy/MM/dd").format(Calendar.getInstance().getTime());
	    	String path = type + File.separator + format;
	    	String upload = client.upload(path, fileItem);
	    	LOGGER.info("file upload {} content-Type:{} size:{} success!!!", upload, file.getContentType(), file.getSize());
	    	resp.setSuccess(true);
	    	String ftppath = SimpleChaos.chaosPath(upload);
	    	Map<String, String> map = new HashMap<>();
	    	String contextPath = WebContextUtil.getContextPath(request);
	    	map.put("downloadUri", contextPath+"file/download/"+ftppath);
	    	map.put("viewUri", contextPath+"file/view/"+ftppath);
	    	resp.setData(map);
	    	return resp;
    	} finally {
			if(fileItem != null) {
				fileItem.delete();
			}
		}
    }

    @GetMapping("download/{file}")
    public void download(@PathVariable("file") String file, HttpServletResponse resp) throws IOException {
		file = SimpleChaos.chaosPath(file);
		if(validateFilePath(file)) {
			int length = client.transfer(file, resp.getOutputStream());
			resp.addHeader("Content-Disposition", "attachment;filename=" + file.substring(file.lastIndexOf(File.separator) + 1));
            resp.setContentType("application/octet-stream");
            resp.addHeader("Content-Length", "" + length);
	    	LOGGER.info("file download {} success!!!", file);
		} else {
	    	LOGGER.info("file download {} failt!!!", file);
			resp.setStatus(404);
			resp.getWriter().write("file :"+file+", can not find!!!");
		}
    }

    @GetMapping("view/{file}")
    public void view(@PathVariable("file") String file, HttpServletResponse resp) throws IOException {
		file = SimpleChaos.chaosPath(file);
		if(validateFilePath(file)) {
			int length = client.transfer(file, resp.getOutputStream());
			resp.addHeader("Content-Disposition", "attachment;filename=" + file.substring(file.lastIndexOf(File.separator) + 1));
            resp.setContentType("application/octet-stream");
            resp.addHeader("Content-Length", "" + length);
	    	LOGGER.info("file view {} success!!!", file);
		} else {
	    	LOGGER.info("file view {} failt!!!", file);
			resp.setStatus(404);
			resp.getWriter().write("file :"+file+", can not find!!!");
		}
    }
    
	private boolean validateFilePath(String file) {
		if(!StringUtils.hasText(file))
		    return false;
		if(file.contains("."+File.separator))
			return false;
		if(file.startsWith(File.separator))
			file = file.substring(1);
		String dir = file.substring(0, file.indexOf(File.separator));
		if(!StringUtils.hasText(dir))
			return false;
		return FILETYPES.contains(dir);
	}
}
